﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using System.Text;
using System.Security;
using System.IO;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Xml;
using System.Xml.Linq;
using System.Linq;
using System.Threading.Tasks;
using System.Threading;
using System.Diagnostics;

namespace TileDownLoader.Elevation
{
    public class GElevation:IElevation
    {
        //http://maps.googleapis.com/maps/api/elevation/xml?locations=39.7391536,-104.9847034&sensor=false
        //<?xml version="1.0" encoding="UTF-8"?> 
        //<ElevationResponse> 
        // <status>OK</status> 
        // <result> 
        //  <location> 
        //   <lat>39.7391536</lat> 
        //   <lng>-104.9847034</lng> 
        //  </location> 
        //  <elevation>1608.6379395</elevation> 
        // </result> 
        //</ElevationResponse> 

        const string urlTemplate = @"http://maps.googleapis.com/maps/api/elevation/xml?locations={0},{1}&sensor=false";
        const string UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7";
        const int Timeout = 30 * 1000;

        public void UpdateElevationData(List<dynamic> listWpt, bool forceUpdate,string format, BackgroundWorker wrker)
        {
            #region Parallel For Loop
            // Google Throws Error because of flood of requests so careful
            //Parallel.For(0, listWpt.Count, index =>
            //    {
            //        dynamic item = listWpt[index];

            //        if (forceUpdate || string.IsNullOrWhiteSpace(item.ele))
            //        {

            //            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(string.Format(urlTemplate, item.lat.Trim(), item.lon.Trim()));

            //            request.UserAgent = UserAgent;
            //            request.Timeout = Timeout;
            //            request.ReadWriteTimeout = Timeout * 6;
            //            request.Accept = "*/*";

            //            using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
            //            {
            //                var eleData = XDocument.Load(response.GetResponseStream());

            //                var query = from result in eleData.Descendants("result") select result.Element("elevation").Value;

            //                item.ele = query.First<string>();
            //            }
            //        }

            //        wrker.ReportProgress((int)(((float)(index + 1) / (float)listWpt.Count) * 100.0), string.Format(format, index + 1, listWpt.Count));
            //    }); 
            #endregion

            #region Parallel For Each
            // Google Throws Error because of flood of requests so careful
            int index = 0;

            ParallelOptions options = new ParallelOptions();

            options.MaxDegreeOfParallelism = 4;

            Parallel.ForEach<dynamic>(listWpt, options, item =>
            {
                if (forceUpdate || string.IsNullOrWhiteSpace(item.ele))
                {

                    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(string.Format(urlTemplate, item.lat.Trim(), item.lon.Trim()));

                    request.UserAgent = UserAgent;
                    request.Timeout = Timeout;
                    request.ReadWriteTimeout = Timeout * 6;
                    request.Accept = "*/*";

                    using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
                    {
                        var eleData = XDocument.Load(response.GetResponseStream());

                        Debug.Print(eleData.ToString());

                        var query = from result in eleData.Descendants("result") select result.Element("elevation").Value;

                        item.ele = query.First<string>();
                    }
                }

                Interlocked.Increment(ref index);

                wrker.ReportProgress((int)(((float)(index) / (float)listWpt.Count) * 100.0), string.Format(format, index, listWpt.Count));
            }); 
            #endregion 

            #region Single Threaded
            //for (int index = 0; index < listWpt.Count; index++)
            //{
            //    dynamic item = listWpt[index];

            //    if (forceUpdate || string.IsNullOrWhiteSpace(item.ele))
            //    {

            //        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(string.Format(urlTemplate, item.lat.Trim(), item.lon.Trim()));

            //        request.UserAgent = UserAgent;
            //        request.Timeout = Timeout;
            //        request.ReadWriteTimeout = Timeout * 6;
            //        request.Accept = "*/*";

            //        using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
            //        {
            //            var eleData = XDocument.Load(response.GetResponseStream());

            //            var query = from result in eleData.Descendants("result") select result.Element("elevation").Value;

            //            item.ele = query.First<string>();
            //        }
            //    }

            //    wrker.ReportProgress((int)(((float)(index + 1) / (float)listWpt.Count) * 100.0), string.Format(format, index + 1, listWpt.Count));
            //} 
            #endregion
        }
    }
}
